package com.info.zhiduoduo.admin.interceptor;

import com.info.zhiduoduo.common.annotation.ZddTask;
import com.info.zhiduoduo.common.utils.DateUtil;
import com.info.zhiduoduo.common.utils.ExceptionUtil;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.repository.entity.system.SystemScheduleTask;
import com.info.zhiduoduo.repository.entity.system.SystemScheduleTaskItem;
import com.info.zhiduoduo.repository.mapper.system.SystemScheduleTaskMapper;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;

/**
 * 处理zdd定时任务的自动记录执行结果
 *
 * @author bob
 * @time 2021/11/30 9:05
 */
@Slf4j
@Aspect
@Component
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ZddTaskAspect {

	@Autowired
	HttpServletRequest httpServletRequest;
	@Resource
	SystemScheduleTaskMapper systemScheduleTaskMapper;

	@Value("${schedule.enabled}")
	private boolean enabled;

	@Pointcut("@annotation(com.info.zhiduoduo.common.annotation.ZddTask)")
	public void excudeService() {
	}

	@Around("excudeService()")
	public void around(ProceedingJoinPoint jp) throws Throwable {
		long start = System.currentTimeMillis();
		Date startTime = DateUtil.nowTime();

		MethodSignature ms = (MethodSignature) jp.getSignature();
		Method method = ms.getMethod();
		String methodName = ms.getName();
		ZddTask anno = AnnotationUtils.getAnnotation(method, ZddTask.class);
		if (anno == null) return;

		String taskName = anno.name();
		SystemScheduleTask scheduleTask = systemScheduleTaskMapper.getByTaskName(taskName);

		// 检查是否可以执行此定时任务
		if (!enabled) return;
		if (!NumberUtil.equals(scheduleTask.getState(), 1)) {
			log.info("定时任务【{}】已关闭，取消执行", taskName);
			return;
		}

		log.info("TASK START====================【Method : {}】【TaskName : {}】====================", methodName, taskName);

		SystemScheduleTaskItem taskItem = new SystemScheduleTaskItem().setTaskId(scheduleTask.getId())
				.setTaskName(scheduleTask.getTaskName())
				.setExecTime(startTime);
		try {
			// 继续执行方法
			Object obj = jp.proceed();

			// 执行成功，记录结果
			String result = "";
			if (obj != null) result = String.valueOf(obj);
			taskItem.setResult(result).setState(1);
		} catch (Exception e) {
			// 记录失败的报错信息
			log.error("执行定时任务【{}】报错", taskName, e);
			taskItem.setError(ExceptionUtil.getErrorStackTrace(e)).setState(2);
		} finally {
			long duration = System.currentTimeMillis() - start;
			log.info("消耗的时间(毫秒): " + duration);

			// Update records
			taskItem.setDuration(duration).insert();
			scheduleTask.setLastExecTime(startTime).updateById();
			log.info("TASK END====================【Method : {}】【TaskName : {}】====================", methodName, taskName);
		}
	}
}
